package net.hands.common.th;

import net.hands.common.StringUtils;
import net.hands.common.coll.KVMap;

/**
 * 说明:simple运行异常类 <br>
 * <p>
 * 这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。
 * </p>
 * 
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
@SuppressWarnings("serial")
public abstract class RuntimeExceptionEx extends RuntimeException {
	/**
	 * 属性容器
	 */
	private final KVMap attributes = new KVMap();

	private static String msg(final Throwable cause) {
		Throwable th = cause;
		while (th != null) {
			final String msg = th.getLocalizedMessage();
			if (StringUtils.hasText(msg)) {
				return msg;
			}
			th = th.getCause();
		}
		return null;
	}

	/**
	 * 
	 * Constructor Method
	 * 
	 * @update 2012-9-25 上午10:21:50
	 * @param msg
	 *            信息
	 * @param cause
	 *            异常类
	 */
	public RuntimeExceptionEx(final String msg, final Throwable cause) {
		super(StringUtils.hasText(msg) ? msg : msg(cause), cause);
	}

	/**
	 * 说明:在属性容器中存放 键值信息
	 * 
	 * @param key
	 *            键
	 * @param val
	 *            值
	 * @return RuntimeExceptionEx
	 * @update 2012-9-25 上午10:21:54
	 */
	public RuntimeExceptionEx putVal(final String key, final Object val) {
		attributes.add(key, val);
		return this;
	}

	/**
	 * 说明:获得属性值
	 * 
	 * @param key
	 *            主键
	 * @return Object
	 * @update 2012-9-25 上午10:22:37
	 */
	public Object getVal(final String key) {
		return attributes.get(key);
	}

	/**
	 * 说明:由于..实例化运行异常
	 * 
	 * @param exClazz
	 *            异常类
	 * @param msg
	 *            信息
	 * @return <T extends RuntimeException> T
	 * @update 2012-9-25 上午10:23:33
	 */
	@SuppressWarnings("unchecked")
	public static <T extends RuntimeExceptionEx> T _of(final Class<T> exClazz,
			final String msg) {
		return (T) _of(exClazz, msg, null);
	}

	/**
	 * 说明:由于..实例化运行异常
	 * 
	 * @param exClazz
	 *            异常类
	 * @param msg
	 *            信息
	 * @param throwable
	 *            所有错误或异常的超类
	 * @return <T extends RuntimeException> T
	 * @update 2012-9-20 上午10:21:27
	 */
	public static RuntimeException _of(
			final Class<? extends RuntimeExceptionEx> exClazz,
			final String msg, Throwable throwable) {
		// 异常为空
		if (throwable == null) {
			try {// 构造异常
				return exClazz.getConstructor(String.class, Throwable.class)
						.newInstance(msg, null);
			} catch (final Exception e) {
			}
		}
		// 异常类是否属于运行期异常
		if (throwable instanceof RuntimeException) {
			return (RuntimeException) throwable;
		} else {
			try {
				// 构建一个运行期间 异常
				return exClazz.getConstructor(String.class, Throwable.class)
						.newInstance(msg,
						// 非RuntimeException运行期异常
								ThrowableUtils.convertThrowable(throwable));
			} catch (final Throwable e) {
				e.printStackTrace();
			}
			return null;
		}
	}
}
